Recoil を使ったオートセーブ機能についての考察
Recoil は Atom と ReadOnlySelector だけで実装できる範囲なら非常にシンプルに書ける 現実のユースケースでは残念ながらそうでない「複雑な状態管理」がある
そのひとつがオートセーブ機能
この Scrapbox のように、書いたそばからどんどんアップロードされていく機能という意味
ユーザーが能動的に保存ボタンを押す場合はオートセーブではない
オートセーブの度し難いところ
データをアップロードする時間がかかるので、ローカルの状態とサーバの状態が常に一致しない
ローカルの変更が頻繁に起こる場合、アップロードする回数を減らす必要がある
古いアップロードが終わらないうちに新しいアップロードが完了してしまうと、あとから古い状態で上書きされる恐れがある
オートセーブが今どんな状態にあるのかをユーザーに適切に伝える必要がある
例えば、「今はアップロード中です」とか「全てのアップロードが完了しました」と伝えたりする
React + 状態管理ライブラリを使っていると、実は表示が一番厄介だったりするteramotodaiki.icon
状態を表示する=状態を Subscribe して Component を再描画するという事なので、でっかい関数1つで全部処理しちゃうと後から表示できなくて困るし、かといってローカルの変更が頻繁すぎると再描画コストが無視できないので本当に必要な状態だけを Subscribe したい teramotodaiki.icon
1. ReadWriteSelector を使った実装方法
https://gyazo.com/252b2fbfa4fceb779bf9d9f66bd15bcf
赤が Atom, 青が ReadOnlySelector, 紫が ReadWriteSelector
自動保存したい Value ひとつにつき、 number の Atom で Reserved と Completed 、boolean の Atom で Uploading を追加する
Reserved: ローカルが更新されるたびに1ずつインクリメントされるカウンタ
Completed: 最後に保存された時の Reserved の値
Reserved > Completed であれば未アップロードの更新がある
→ Now Saved? Selector
Uploading: 今アップロード処理を行っているかどうか表すフラグ
Reserve Uploading (ReadWriteSelector)
どんどん更新したい値を突っ込む
Value と Reserved はアトミックに更新しなきゃダメ
どちらか片方だけが更新された状態でアップロード処理が始まったらおかしなことになる
Uploader (ReadWriteSelector)
アップロード処理を書く部分。 set 関数だけを使う。正直コレは Selector でなくても良い
一度どこかで get すればいいのだが、役割が分かりづらいので困る
Reserve Uploading から set することで set 関数のアップロード処理を起動させても良い
そんな方法で Atom を Subscribe 出来るのだろうか?
→ できない。set 関数の中で使える get はその時点での値を得るための関数であり Subscribe ではない
"非同期処理が終わったときに Atom を変更する" という操作は、コンポーネントからしか出来ない
非同期で set を受け取ることができないことが問題
メモ
Uploader は rxjs で書いて組み込めばいいんじゃないか?
定期的なパルスを与えるための interval(1000) から Selector をつくれないか?